package ru.spbu.math.android.cbrf.dataprovider.randomprovider;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Date;
import java.util.Map;

import ru.spbu.math.android.cbrf.dataprovider.IProvider;
import ru.spbu.math.android.cbrf.dataprovider.UnavailableValueException;
import ru.spbu.math.android.cbrf.model.Category;
import ru.spbu.math.android.cbrf.model.Rate;
import ru.spbu.math.android.cbrf.model.RateType;

/**
 * Class for getting random data
 * 
 */

public class RandomProvider implements IProvider {

	private static final String NAME = "RandomProvider";
	private RateTypeStore instance = RateTypeStore.Instance();

	private Map<String, Rate> previousRate = new HashMap<String, Rate>();

	@Override
	public Rate getCurrentRate(String id) throws UnavailableValueException {

		int throwException = instance.throwException(id);

		if (throwException > 0) {
			throw new UnavailableValueException();
		} else if ((throwException == 0) && (Math.random() > 0.5)) {
			throw new UnavailableValueException();
		}

		double value = Math.random() * 100;
		Rate rate = new Rate(instance.findRateTypeById(id), value,
				getDifference(id, value), Calendar.getInstance().getTime());

		setAsCurrent(rate);
		return rate;
	}

	@Override
	public List<Rate> getDynamicRates(String id, Date since, Date until)
			throws UnavailableValueException {
		int throwException = instance.throwException(id);

		if (throwException > 0) {
			throw new UnavailableValueException();
		} else if ((throwException == 0) && (Math.random() > 0.5)) {
			throw new UnavailableValueException();
		}
		
		RateType rateType = instance.findRateTypeById(id);
		ArrayList<Rate> rateList = new ArrayList<Rate>();
		long time = since.getTime();
		while (time <= until.getTime()) {
			double value = Math.random() * 100;
			rateList.add(new Rate(rateType, value, getDifference(id, value),
					new Date(time)));
			time += 86400000;
		}
		return rateList;
	}

	@Override
	public List<Category> getCategories() {
		return instance.getCategories();
	}

	@Override
	public List<RateType> getRateTypeByCategory(Category category) {
		return instance.getRateTypeByCategory(category);
	}

	@Override
	public String getName() {
		return NAME;
	}

	private double getDifference(String id, double currentValue) {
		Rate previous = previousRate.get(id);
		if (previous == null) {
			return currentValue - Math.random() * 100;
		} else {
			return currentValue - previous.getValue();
		}
	}

	/**
	 * Try to set this Rate as current for this id.
	 * 
	 * @param newRate
	 */
	private void setAsCurrent(Rate newRate) {
		if (newRate != null) {
			String id = newRate.getResource().getId();
			Rate previous = previousRate.get(id);

			if (previous == null) {
				// we haven't current Rate for this id yet
				previousRate.put(id, newRate);
			} else if (newRate.getDate().after(previous.getDate())) {
				// we have previous Rate that is older than newRate
				previousRate.put(id, previous);
			}
		}
	}
}
